package com.example.demo.spring.aop;

import com.example.demo.spring.aop.annotation.PointCut;
import com.example.demo.spring.aop.proxy.AbsMethodAdvance;
import com.example.demo.spring.aop.util.ClassUtil;
import com.example.demo.spring.aop.util.ReflectionUtil;

import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: htc
 * @date: Created in 13:31 2019/2/20.
 */
public class ApplicationContext {
    /**
     * 存放代理类的集合
     */
    public static ConcurrentHashMap<String, Object> proxyBeanMap = new ConcurrentHashMap<String, Object>();

    static {
        initAopBeanMap("com.example.swap.spring.aop.swap");
    }

    /**
     * 初始化 aop 容器
     *
     * @param basePath
     */
    public static void initAopBeanMap(String basePath) {
        try {
            Set<Class<?>> classSet = ClassUtil.getClassSet(basePath);

            for (Class clazz : classSet) {
                //找到切面
                Method[] methods = clazz.getMethods();

                for (Method method : methods) {
                    if (method.isAnnotationPresent(PointCut.class)) {
                        //找到切点
                        PointCut pointCut = (PointCut) method.getAnnotations()[0];
                        String pointCutStr = pointCut.value();
                        String[] pointCutArr = pointCutStr.split("_");

                        //被代理的类名
                        String className = pointCutArr[0];
                        //被代理的方法名
                        String methodName = pointCutArr[1];

                        //根据切点 创建被代理对象
                        Object targetObj = ReflectionUtil.newInstance(className);

                        //根据切面类创建代理者
                        AbsMethodAdvance proxyer = (AbsMethodAdvance) ReflectionUtil.newInstance(clazz);
                        //设置代理的方法
                        proxyer.setProxyMethodName(methodName);

                        Object object = proxyer.createProxyObject(targetObj);

                        if (null != object) {
                            proxyBeanMap.put(targetObj.getClass().getSimpleName().toLowerCase(), object);
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
